// [[ OnflowGenerator File UUID: 52f8c37ba12340dea9257d6a7ee3a7a9  ]]
package com.itdct.onflow.system.file.service

import com.itdct.onflow.core.constant.CommonString
import com.itdct.onflow.core.constant.ReturnCode
import com.itdct.onflow.core.extend.*
import com.itdct.onflow.core.util.FileSizeUtil
import com.itdct.onflow.core.vo.KeyLabelValueVo
import com.itdct.onflow.core.vo.RespPageVo
import com.itdct.onflow.core.vo.RespVo
import com.itdct.onflow.system.common.base.BaseSysService
import com.itdct.onflow.system.common.context.Context
import com.itdct.onflow.system.common.extend.dict
import com.itdct.onflow.system.file.constant.SysFileSourceType
import com.itdct.onflow.system.file.entity.SysFileEntity
import com.itdct.onflow.system.file.manager.SysFileManager
import com.itdct.onflow.system.file.manager.upload.BaseFileTransfer
import com.itdct.onflow.system.file.mapper.SysFileMapper
import com.itdct.onflow.system.file.qo.SysFileEditQo
import com.itdct.onflow.system.file.qo.SysFileSearchQo
import com.itdct.onflow.system.file.qo.SysFileUploadQo
import com.itdct.onflow.system.file.vo.SysFileDetailVo
import com.itdct.onflow.system.file.vo.SysFileListVo
import com.itdct.onflow.system.file.vo.SysFileUploadVo
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.net.URLEncoder

/**
 * @author DCTANT
 * @date 2025-09-23 16:16:15
 * @version 1.0
 * @description 系统文件管理服务
 */
@Service
class SysFileService(
    val sysFileMapper: SysFileMapper,
    val baseFileTransfer: BaseFileTransfer,
    val sysFileManager: SysFileManager
) : BaseSysService() {

    @Transactional(rollbackFor = [Exception::class])
    fun add(qo: SysFileEditQo, context: Context): RespVo<Long> {
        val addEntity = qo.toEntity(SysFileEntity::class.java)
        val id = sysFileMapper.insertEx(addEntity)
        return success(id)
    }

    @Transactional(rollbackFor = [Exception::class])
    fun update(qo: SysFileEditQo, context: Context): RespVo<Unit> {
        val updateEntity = sysFileMapper.selectByIdEx(qo.id)
        qo.injectValue(updateEntity)
        sysFileMapper.updateEx(updateEntity)
        return success()
    }

    fun delete(qo: SysFileEditQo, context: Context): RespVo<Unit> {
        val ids = qo.ids ?: fail(ReturnCode.LACK_PARAM, CommonString.REQUIRE_DELETE_ID_LIST)
        val deleteEntities = sysFileMapper.selectByIdsEx(ids)
        sysFileMapper.deleteBatchEx(deleteEntities)

        for (deleteEntity in deleteEntities) {
            baseFileTransfer.delete(deleteEntity)
        }
        return success()
    }

    fun detail(qo: SysFileSearchQo, context: Context): RespVo<SysFileDetailVo> {
        val id = qo.id ?: fail(ReturnCode.LACK_PARAM, CommonString.REQUIRE_ID)
        val vo = sysFileMapper.findById(id) ?: fail(CommonString.ENTITY_NOT_FOUND_USAGE("系统文件管理", id))
        return success(vo.dict())
    }

    fun page(qo: SysFileSearchQo, context: Context): RespPageVo<SysFileListVo> {
        startPage(context)
        val pageData = sysFileMapper.findByList(qo)
        pageData.forEach {
            it.fileSizeName = FileSizeUtil.formatFileSize(it.fileSize)
        }
        return successPage(pageData.dict())
    }

    fun uploadFile(qo: SysFileUploadQo, context: Context): RespVo<SysFileUploadVo> {
        val dto = sysFileManager.transferToLocal(qo.file, qo.moduleName)
        val localFile = dto.localFile ?: fail("文件传输失败")
        val originFileName = dto.originFileName
        val moduleName = dto.moduleName

        val sysFileEntity = sysFileManager.uploadFile(localFile, originFileName, moduleName, qo.fileGrade, SysFileSourceType.USER_UPLOAD, qo.expireDate, deleteAfterUpload = true)

        val sysFileUploadVo = SysFileUploadVo()
        sysFileUploadVo.id = sysFileEntity.id!!
        sysFileUploadVo.fileName = sysFileEntity.fileName
        sysFileUploadVo.originFileName = sysFileEntity.originFileName
        sysFileUploadVo.storePath = sysFileEntity.storePath
        sysFileUploadVo.md5 = sysFileEntity.md5
        sysFileUploadVo.fileSize = sysFileEntity.fileSize
        return success(sysFileUploadVo)
    }

    fun download(id: Long, context: Context): RespVo<Unit> {
        val sysFileEntity = sysFileMapper.selectByIdEx(id)
        val inputStream = baseFileTransfer.download(sysFileEntity.storePath)
        val response = context.response ?: fail("无法找到响应对象")
        response.contentType = "application/octet-stream"
        response.setContentLengthLong(sysFileEntity.fileSize)
        response.setHeader("Content-Disposition", "attachment;filename=\"${URLEncoder.encode(sysFileEntity.originFileName, "UTF-8")}\"")
        response.outputStream?.write(inputStream.readBytes())
        return success()
    }

// [[ OnflowGenerator Range (- selectFunctions -) Start ]]

    fun selectFileNameList(qo: SysFileSearchQo, context: Context): RespVo<List<KeyLabelValueVo>> {
        val vos = sysFileMapper.selectFileNameList(qo)
        return success(vos)
    }
// [[ OnflowGenerator Range (- selectFunctions -) End ]]
}